window.setTimeout(function () {
    $('head').append(`<style>
.ksa-piceditor-container {background: #222;color: #636363;display: flex;width: 100%;height: 100%;}
        .ksa-piceditor-tools {display: flex;flex-direction: column;gap: 10px;}
        .ksa-piceditor-canvas-container {width: 100%;height: 100%;flex: 1;position: relative;overflow: hidden;display: flex;align-items: center;justify-content: center;background: #111111;}
        .ksa-piceditor-canvas-container:focus {outline: none;}
        .ksa-piceditor-canvas-wrapper {position: absolute;transform-origin: 0 0;}
        .effects {display: flex;flex-direction: column;gap: 10px;padding: 10px;border: 1px solid #ccc;}
        .ksa-piceditor-mode-group {display: flex;}
        .ksa-piceditor-mode-group > div {padding:5px;border-right: #353535 1px solid;}
        .ksa-piceditor-mode-group > div[active] {background: #111;color: #c7c7c7;}
        .selected-path {outline: 2px dashed #0066ff;}
        .ksa-piceditor-brush-settings {display: flex;flex-direction: column;border: 1px solid #333;cursor: default;}
        .ksa-piceditor-brush-settings-item {background: #111;padding: 10px;}
        .ksa-piceditor-brush-settings-item-li {padding: 5px 0;display: flex;}
        .ksa-piceditor-brush-settings-item-li > label {display: block;width:80px;}
        .ksa-piceditor-brush-settings-item-li > div {width: 100%;flex: 1;}
        .ksa-piceditor-brush-settings-item-li > span {display: block;width: 70px;text-align: center;}
        .ksa-piceditor-brush-settings-item-li > span input {background: none;border: none;width: 100%;color:inherit;text-align: center;}
        .ksa-piceditor-delete-btn {position: absolute;background: red;color: white;border: none;border-radius: 50%;width: 20px;height: 20px;line-height: 20px;text-align: center;cursor: pointer;font-size: 12px;transform: translate(-50%, -50%);z-index: 999;}
        .ksa-piceditor-canvas-wrapper-canvas { display: block}
        .ksa-piceditor-canvas-wrapper-canvas-temp {position: absolute;left: 0;top: 0;z-index: 2}
        .ksa-piceditor-canvas-wrapper-canvas-crop {position: absolute;left: 0;top: 0;z-index: 3; display: none;}
        .ksa-piceditor-btn {height: 26px;line-height: 26px;padding: 0 5px;display: inline-block;overflow: hidden;border: #555 1px solid;border-radius: 4px;background: #262935;cursor: pointer;user-select: none;}
        .ksa-piceditor-btn:hover {border-color: #666;color: #999;}
        .ksa-piceditor-btn[upload] {position: relative;overflow: hidden;padding: 0;}
        .ksa-piceditor-btn[upload] label {display: block;padding: 0 5px;cursor: pointer;}
        .ksa-piceditor-btn[upload] input {opacity: 0;position: absolute;width: 0;height: 0}
</style>`);
}, 10);

Vue.component('pic-editor', {
        template: `<div class="ksa-piceditor-container">
            <div class="ksa-piceditor-tools">

                <div style="padding: 5px 5px 0; text-align: center;">
                    <div class="ksa-piceditor-btn" upload><label><span icon="file-image"></span>上传<input type="file" accept="image/*" @change="handleImageUpload"></label></div>
                    <div class="ksa-piceditor-btn" @click="undo"><span icon="arrow-go-back"></span>撤销</div>
                    <div class="ksa-piceditor-btn" @click="clearEmpty"><span icon="brush-2"></span>清空</div>
                </div>

                <div class="ksa-piceditor-brush-settings">
                    <div class="ksa-piceditor-mode-group">
                        <div @click="changeMode('draw')" :active="mode == 'draw'">画笔</div>
                        <div @click="changeMode('brush')" :active="mode == 'brush'">毛笔</div>
                        <div @click="changeMode('select')" :active="mode == 'select'">选择</div>
                        <div @click="changeMode('lasso')" :active="mode == 'lasso'">套索</div>
                        <div @click="changeMode('crop')" :active="mode == 'crop'">裁剪</div>
                    </div>
                    <div class="ksa-piceditor-brush-settings-item">
                        <div v-if="mode == 'crop'">
                            <div class="ksa-piceditor-brush-settings-item-li">
                                <label>透视裁剪:</label>
                                <div><label><input type="checkbox" min="0" max="200" v-model="Crop.isTransform">是</label></div>
                            </div>
                        </div>
                        <div v-if="mode == 'draw' || mode == 'brush'">
                            <div class="ksa-piceditor-brush-settings-item-li">
                                <label>画笔颜色:</label>
                                <div><input type="color" value="#000000" v-model="Brush.color" @input="updateBrushSettings"></div>
                                <span>{{Brush.color}}</span>
                            </div>
                            <div class="ksa-piceditor-brush-settings-item-li">
                                <label>画笔粗细:</label>
                                <div><input type="range" min="1" max="50" v-model="Brush.width" @input="updateBrushSettings"></div>
                                <span><input type="number" v-model="Brush.width" min="1" max="50" @input="updateBrushSettings"></span>
                            </div>
                            <div class="ksa-piceditor-brush-settings-item-li">
                                <label>画笔透明度:</label>
                                <div><input type="range" min="1" max="100" v-model="Brush.opacity" @input="updateBrushSettings"></div>
                                <span><input type="number" v-model="Brush.opacity" min="1" max="100" @input="updateBrushSettings"></span>
                            </div>
                        </div>
                        <div v-if="mode == 'lasso'">
                            <div class="ksa-piceditor-brush-settings-item-li">
                                <label>羽化:</label>
                                <div><input type="range" min="0" max="50" v-model="featherValue"></div>
                                <span><input type="number" v-model="featherValue" min="0" max="50"></span>
                            </div>
                            <div class="ksa-piceditor-brush-settings-item-li">
                                <label>羽化填充:</label>
                                <div><input type="color" value="#ffffff" v-model="featherColor"></div>
                                <span>{{featherColor}}</span>
                            </div>
                        </div>
                    </div>
                </div>


                <div class="ksa-piceditor-brush-settings">
                    <div class="ksa-piceditor-mode-group">
                        <div active>图片效果</div>
                    </div>
                    <div class="ksa-piceditor-brush-settings-item">
                        <div>
                            <div class="ksa-piceditor-brush-settings-item-li">
                                <label>高斯模糊:</label>
                                <div><input type="range" min="0" max="100" v-model="blurValue" @input="applyEffects"></div>
                                <span><input type="number" v-model="blurValue" min="0" max="20" @keydown.enter.stop="applyEffects"></span>
                            </div>
                            <div class="ksa-piceditor-brush-settings-item-li">
                                <label>饱和度:</label>
                                <div><input type="range" min="0" max="200" v-model="saturationValue" @input="applyEffects"></div>
                                <span><input type="number" v-model="saturationValue" min="0" max="200" @keydown.enter.stop="applyEffects"></span>
                            </div>
                            <div class="ksa-piceditor-brush-settings-item-li">
                                <label>亮度:</label>
                                <div><input type="range" min="0" max="200" v-model="brightnessValue" @input="applyEffects"></div>
                                <span><input type="number" v-model="brightnessValue" min="0" max="200" @keydown.enter.stop="applyEffects"></span>
                            </div>
                            <div class="ksa-piceditor-brush-settings-item-li">
                                <label>反向:</label>
                                <div><label><input type="checkbox" min="0" max="200" v-model="reversalColorValue" @change="reversalColorValueChange">是</label></div>
                            </div>
                        </div>
                    </div>
                </div>
            </div>
            <div class="ksa-piceditor-canvas-container" @mousedown="handleMouseDown" @mousemove="handleMouseMove" @mouseup="handleMouseUp" @wheel="canvasWrapperZoom" @keydown="handleKeyDown" @contextmenu="handleRightClickDisabled" tabindex="-1">
                <div class="ksa-piceditor-canvas-wrapper">
                    <canvas class="ksa-piceditor-canvas-wrapper-canvas"></canvas>
                    <canvas class="ksa-piceditor-canvas-wrapper-canvas-temp"></canvas>
                    <canvas class="ksa-piceditor-canvas-wrapper-canvas-crop"></canvas>
                </div>
            </div>
        </div>`,
        data(){
            return {
                mode : 'draw', // 当前绘画模式，包括draw, brush, select, lasso
                currentImage : null, // 当前显示的图片
                originalImage : null, // 保存原始图片
                isDrawing : false, // 是否正在绘画

                selectedPathIndex : -1, // 当前选中的路径索引
                dragStartPos : null, // 拖拽开始的位置
                lastPoint : null, // 最后一个点的位置
                lastTime : null, // 最后一个点的时间
                backgroundColor : '#ffffff', // 背景颜色
                //画笔数据
                Brush : {
                    width : 1, // 当前画笔线宽
                    color : '#000000', // 当前画笔颜色
                    opacity : 100, //当前画笔透明度
                },
                //选择模式 选择框
                Selection : {
                    Active : false, //是否激活
                    Type : 'solid', //选择框类型 solid=实线
                    Color:'#0066ff', //选择框颜色
                    FillStyle : 'rgba(0, 102, 255, 0.1)', //填充颜色
                    Start : {x:0, y:0}, //起点位置
                    End : {x:0, y:0}, //结束位置
                },
                scale : 1, // 当前缩放比例
                translateX : 0, // 当前水平平移距离
                translateY : 0, // 当前垂直平移距离
                isDragging : false, // 是否正在拖拽
                selectedPaths : new Set(), // 选中的路径集合
                pressStartTime : null, // 按下开始的时间
                featherValue : 0, // 羽化值
                featherColor : '#ffffff', // 羽化颜色
                reversalColorValue : false, //是否反向

                // 效果相关状态
                blurValue : 0, // 模糊值
                saturationValue : 100, // 饱和度值
                brightnessValue : 100, // 亮度值
                polygon : {
                    isDrawing : false, // 是否正在绘制多边形
                    isComplete : false, // 是否完成多边形绘制
                    lineColor : 'red', // 线条颜色
                    lineWidth : 1,  // 线条宽度
                },
                //裁剪框
                Crop : {
                    //裁剪框坐标
                    Box : {
                        left : 0,
                        top : 0,
                        tl : {x:0,y:0}, //左上角坐标
                        tr : {x:0,y:0}, //右上角坐标
                        bl : {x:0,y:0}, //左下角坐标
                        br : {x:0,y:0}, //右下角坐标
                    },
                    ActionID : 0, //裁剪指令ID 0=No 1=符合触发 2=开始缩放裁剪区域
                    Action : null, //裁剪触发的边角名称
                    isTransform : false, //是否为透视裁剪
                },
            };
        },
        mounted(){
            this.dom_canvas_container = this.$el.querySelector('.ksa-piceditor-canvas-container');
            this.dom_canvas_wrapper = this.$el.querySelector('.ksa-piceditor-canvas-wrapper');
            this.dom_canvas = this.$el.querySelector('canvas.ksa-piceditor-canvas-wrapper-canvas');
            this.dom_ctx = this.dom_canvas.getContext('2d');
            this.dom_canvas_temp = this.$el.querySelector('canvas.ksa-piceditor-canvas-wrapper-canvas-temp');
            this.dom_ctx_temp = this.dom_canvas_temp.getContext('2d');

            this.Crop.Canvas = this.$el.querySelector('canvas.ksa-piceditor-canvas-wrapper-canvas-crop');
            this.Crop.Ctx = this.Crop.Canvas.getContext('2d');

            this.updateBrushSettings();

            this.polygon_points = []; // 存储当前正在绘制多边形的点
            this.polygon_GroupPoint = []; //多边形组信息 item=对应多边形点坐标信息
            this.paths = []; // 所有路径的集合
            this.currentPath = []; // 当前路径的点集
            this.canvas_update_callbacl_timmer = null; //画布更新回调计时器对象
            this.$emit('init_call_func', this);
        },
        props: {
            'update_call_canvas' : {
                type : String,
                required : false
            }
        },
        methods : {
            //父组件回调函数
            callFuncUpdate(){
                this.canvas_update_callbacl_timmer && window.clearTimeout(this.canvas_update_callbacl_timmer);
                this.canvas_update_callbacl_timmer = window.setTimeout(()=>{
                    try {
                        this.$emit('update_call_cunc', this.dom_canvas);
                    }catch (e) {

                    }
                    this.copyCanvasContent();
                });
            },
            //复制内容到父组件指定的canvas
            copyCanvasContent() {
                //this.update_call_canvas是一个选择器字符串
                if(!this.update_call_canvas){
                    return;
                }
                const update_call_canvas = $(this.update_call_canvas);

                if(!update_call_canvas.length){
                    return;
                }
                const sourceCanvas = this.dom_canvas;
                const targetCanvas = update_call_canvas[0];
                const targetCtx = targetCanvas.getContext('2d');
                //重设目标canvas大小
                targetCanvas.width = sourceCanvas.width;
                targetCanvas.height = sourceCanvas.height;
                // 清空目标画布
                targetCtx.clearRect(0, 0, targetCanvas.width, targetCanvas.height);

                // 复制源画布内容到目标画布
                targetCtx.drawImage(sourceCanvas, 0, 0);
                update_call_canvas.trigger('change');
            },
            changeMode(name=''){
                const self = this;

                if(name === 'crop'){

                    this.Crop_InitBox();
                }else{
                    if(this.mode === 'crop'){
                        this.Crop_InitDefault();
                    }
                }

                this.mode = name;
                this.selectedPathIndex = -1;
                this.selectedPaths.clear();
                this.removeDeleteButtons();
                this.drawImage();
            },
            // 调整画布大小
            resizeCanvas() {
                if (this.currentImage) {
                    // 根据图片尺寸设置canvas大小
                    let width = this.currentImage.width;
                    let height = this.currentImage.height;

                    // 计算缩放比例
                    const maxWidth = this.dom_canvas_container.clientWidth;
                    const maxHeight = this.dom_canvas_container.clientHeight;
                    const ratio = Math.min(maxWidth / width, maxHeight / height);

                    if (ratio < 1) {
                        width *= ratio;
                        height *= ratio;
                    }

                    this.dom_canvas.width = width;
                    this.dom_canvas.height = height;
                    this.dom_canvas_temp.width = width;
                    this.dom_canvas_temp.height = height;
                } else {
                    this.dom_canvas.width = 800;
                    this.dom_canvas.height = 600;
                    this.dom_canvas_temp.width = this.dom_canvas.width;
                    this.dom_canvas_temp.height = this.dom_canvas.height;
                }
                this.drawImage();
            },
            /**
             * 将屏幕坐标转换为canvas内部相对坐标
             * @param x
             * @param y
             */
            toCanvasXY(x=0, y=0){
                const rect = this.dom_canvas.getBoundingClientRect();
                // 计算相对于canvas的坐标
                x = (x - rect.left) / this.scale;
                y = (y - rect.top) / this.scale;
                return [x, y];
            },
            // 处理鼠标按下事件
            handleMouseDown(e) {
                const self = this;
                const mode = this.mode;
                if (e.button === 2) { // 右键
                    this.isDragging = true;
                    this.dragStartPos = { x: e.clientX - this.translateX, y: e.clientY - this.translateY };
                    e.preventDefault();
                    return;
                }
                if(mode === 'crop') {
                    if (self.Crop.ActionID === 1) {
                        self.Crop.ActionID = 2;
                        return;
                    }
                }
                //获得当前鼠标在canvas中的相对位置
                const [x, y] = self.toCanvasXY(e.clientX, e.clientY);

                if(mode === 'lasso'){
                    this.polygon_start(x, y);
                    return;
                }
                this.isDrawing = true;

                if (mode === 'select') {
                    const Selection = self.Selection;
                    Selection.Active = true;
                    Selection.Start = { x: x, y: y };
                    Selection.End = { x: x, y: y };

                    this.selectedPaths.clear();
                    this.removeDeleteButtons();
                    return;
                }

                if(mode === 'draw' || mode === 'brush'){

                    this.pressStartTime = Date.now();
                    this.currentPath = {
                        type : this.mode,
                        color : this.currentBrushColor,
                        width : this.currentLineWidth,
                        points : [{
                            x,
                            y,
                            width: this.currentLineWidth,
                        }]
                    };
                    this.lastPoint = { x, y };
                    this.lastTime = Date.now();
                }

            },
            // 处理鼠标移动事件
            handleMouseMove(e) {
                const self = this;
                const mode = this.mode;
                //拖动画布
                if (this.isDragging) {
                    this.translateX = e.clientX - this.dragStartPos.x;
                    this.translateY = e.clientY - this.dragStartPos.y;
                    this.canvasWrapperUpdate(); // 更新canvasWrapper的位置和缩放
                    return;
                }
                if(mode === 'lasso'){
                    return;
                }


                //获得当前鼠标在canvas中的相对位置
                const [x, y] = self.toCanvasXY(e.clientX, e.clientY);

                if(mode === 'crop') {
                    if(self.Crop.ActionID !== 2){
                        this.Crop.Action = self.Crop_detectCorner(x, y);
                        this.Crop_updateCursor(this.Crop.Action);
                    }
                    if(!self.Crop.ActionID) {
                        if (this.Crop.Action) {
                            self.Crop.ActionID = 1;
                        }
                    }
                    if (self.Crop.ActionID === 2 && this.Crop.Action) {
                        this.Crop_resizeCropBox(this.Crop.Action, x, y);
                        this.Crop_DrawBox();
                    }
                    return;
                }

                if (!this.isDrawing) return;

                if (mode === 'select') {
                    const Selection = self.Selection;
                    Selection.End = { x: x, y: y };
                    this.drawImage();
                    return;
                }

                if (mode === 'brush') {
                    const currentTime = Date.now();
                    const speed = Math.sqrt(
                        Math.pow(x - this.lastPoint.x, 2) +
                        Math.pow(y - this.lastPoint.y, 2)
                    ) / (currentTime - this.lastTime);

                    this.currentPath.points.push({
                        x,
                        y,
                        width: this.calculateBrushWidth(speed),
                        opacity: 1,
                    });

                    this.lastPoint = { x, y };
                    this.lastTime = currentTime;
                } else if(mode === 'draw') {
                    this.currentPath.points.push({ x, y });
                }
                this.canvasClearEmpty(true);
                this.drawPathLine(this.currentPath, true);
            },
            // 处理鼠标松开事件
            handleMouseUp(e) {
                const self = this;
                const mode = this.mode;
                if (e.button === 2) {
                    this.isDragging = false;
                    return;
                }
                //获得当前鼠标在canvas中的相对位置
                const [x, y] = self.toCanvasXY(e.clientX, e.clientY);

                if(mode === 'lasso'){
                    this.polygon_continue(x, y);
                    return;
                }
                if(mode === 'crop'){
                    this.Crop.ActionID = 0;
                    this.Crop.Action = null;
                    return;
                }
                if (!this.isDrawing) return;
                const Selection = self.Selection;

                if (mode === 'select' && Selection.Active) {
                    // 计算选择框在画布坐标系中的位置
                    const startX = Selection.Start.x;
                    const startY = Selection.Start.y;
                    const endX = Selection.End.x;
                    const endY= Selection.End.y;

                    const minX = Math.min(startX, endX);
                    const maxX = Math.max(startX, endX);
                    const minY = Math.min(startY, endY);
                    const maxY = Math.max(startY, endY);

                    // 检查每条路径是否与选择框相交
                    this.paths.forEach((path, index) => {
                        const bounds = this.getPathBounds(path);
                        // 只要路径边界与选择框有交集就选中
                        if (!(bounds.maxX < minX || bounds.minX > maxX ||
                            bounds.maxY < minY || bounds.minY > maxY)) {
                            this.selectedPaths.add(index);
                        }
                    });

                    Selection.Active = false;
                    Selection.Start = null;
                    Selection.End = null;

                } else if (this.currentPath.points.length > 0) {
                    this.pathsAdd(this.currentPath);
                }

                this.isDrawing = false;
                this.currentPath = {};


                this.canvasClearEmpty(true);
                this.drawImage();
            },
            handleKeyDown(e){
                const self = this;
                const mode = self.mode;
                if(e.key === 'Enter'){
                    if(mode === 'crop'){
                        self.Crop_Apply();
                        return;
                    }
                    if(this.polygon.isDrawing){
                        this.polygon_end();
                    }
                } else if (e.key === 'Escape') {
                    if(this.polygon.isDrawing){
                        this.polygon_cancel();
                    }
                }

            },
            handleRightClickDisabled(e) {
                e.preventDefault();
            },
            // 清空画布并重置为初始状态
            clearEmpty(isConfirm=true, callFunc=null){
                const self = this;
                function _f(){
                    self.currentImage = null; // 当前显示的图片
                    self.originalImage = null; // 保存原始图片
                    self.scale = 1; // 当前缩放比例
                    self.translateX = 0; // 当前水平平移距离
                    self.translateY = 0; // 当前垂直平移距离
                    self.polygon_points = []; // 存储当前正在绘制多边形的点
                    self.polygon_GroupPoint = []; //多边形组信息 item=对应多边形点坐标信息
                    self.paths = []; // 所有路径的集合
                    self.currentPath = []; // 当前路径的点集
                    self.canvasWrapperUpdate();
                    self.canvasClearEmpty(true);
                    self.canvasClearEmpty();
                    self.updateDeleteButtons();
                    self.callFuncUpdate();
                    callFunc && callFunc(self);
                }
                if(isConfirm){
                    $.Dialog('confirm', '操作提示', '确认要清空画布吗？', _f);
                }else {
                    _f();
                }
            },
            //画布父级缩放
            canvasWrapperZoom(e){
                e.preventDefault();
                const rect = this.dom_canvas.getBoundingClientRect();
                const mouseX = e.clientX - rect.left;
                const mouseY = e.clientY - rect.top;

                // 更新缩放比例
                const oldScale = this.scale;
                let newScale = this.scale + (e.deltaY > 0 ? -0.1 : 0.1);
                newScale = Math.max(0.5, Math.min(20, newScale));

                // 由于transform-origin:0 0,需要根据缩放比例变化调整平移量
                const scaleDiff = newScale - oldScale;
                this.translateX = this.translateX - (mouseX * (scaleDiff / oldScale));
                this.translateY = this.translateY - (mouseY * (scaleDiff / oldScale));
                this.scale = newScale;


                this.canvasWrapperUpdate();
            },
            //画布父级位置更新
            canvasWrapperUpdate(){
                this.dom_canvas_wrapper.style.transform = `translate(${this.translateX}px, ${this.translateY}px) scale(${this.scale})`;
            },
            loadImg(img){
                this.currentImage = img;
                this.originalImage = img; // 保存原始图片
                this.resizeCanvas();
                this.callFuncUpdate();
            },
            // 处理图片上传
            handleImageUpload(e) {
                const file = e.target.files[0];
                if (file) {
                    const reader = new FileReader();
                    reader.onload = (event) => {
                        const img = new Image();
                        img.onload = () => {
                            this.loadImg(img);
                        };
                        img.src = event.target.result;
                    };
                    reader.readAsDataURL(file);
                }
            },
            readCanvas_To_Image(canvas){
                const img = new Image();
                img.onload = () => {
                    this.loadImg(img);
                };
                img.src = canvas.toDataURL('image/png'); // 将 canvas 内容转换为数据 URL
            },
            reversalColorValueChange(){
              this.reversalColorValue = !!this.reversalColorValue;
              this.applyEffects();
            },
            /**
             * 创建一个虚拟canvas
             * @param width
             * @param height
             * @return {HTMLCanvasElement}
             */
            createVirtualCanvas(width=0, height=0){
                const tempCanvas = document.createElement('canvas');
                tempCanvas.width = width;
                tempCanvas.height = height;
                return tempCanvas;
            },
            // 应用效果
            applyEffects() {
                if (!this.originalImage) return;

                let tempCanvas = this.createVirtualCanvas(this.dom_canvas.width, this.dom_canvas.height);
                let tempCtx = tempCanvas.getContext('2d');

                // 从原始图像开始应用效果
                tempCtx.drawImage(this.originalImage, 0, 0, tempCanvas.width, tempCanvas.height);

                // 应用模糊
                if (this.blurValue > 0) {
                    tempCtx.filter = `blur(${this.blurValue / 10}px)`;
                    tempCtx.drawImage(tempCanvas, 0, 0);
                }

                // 应用饱和度
                if (this.saturationValue !== 100) {
                    tempCtx.filter = `saturate(${this.saturationValue}%)`;
                    tempCtx.drawImage(tempCanvas, 0, 0);
                }

                // 应用亮度
                if (this.brightnessValue !== 100) {
                    tempCtx.filter = `brightness(${this.brightnessValue}%)`;
                    tempCtx.drawImage(tempCanvas, 0, 0);
                }
                // 应用颜色反转
                if(this.reversalColorValue){
                    tempCtx.filter = 'invert(100%)';
                    tempCtx.drawImage(tempCanvas, 0, 0);
                }
                // 重置滤镜并更新当前图像
                this.dom_ctx.filter = 'none';
                this.currentImage = tempCanvas;
                tempCanvas = null;
                tempCtx = null;
                this.drawImage();
            },
            // 更新画笔设置
            updateBrushSettings() {
                const rgb = this.hexToRgb(this.Brush.color);
                const opacity = this.Brush.opacity / 100;
                this.currentBrushColor = `rgba(${rgb.r},${rgb.g},${rgb.b},${opacity})`;
                this.currentLineWidth = parseInt(this.Brush.width);
            },
            // 计算毛笔效果宽度
            calculateBrushWidth(speed) {

                // 获取基础画笔宽度
                const baseWidth = this.currentLineWidth;
                const pressTime = Date.now() - this.pressStartTime;
                const pressureEffect = Math.min(pressTime / 1000, 2); // 最大2倍
                const speedEffect = Math.max(0.2, speed / 2000);
                let width = baseWidth * pressureEffect * speedEffect;
                // console.log('speed', `speed=${speed}, baseWidth=${baseWidth}, width=${width}, pressTime=${pressTime}`);
                return baseWidth * pressureEffect * speedEffect;
            },
            //添加路径
            pathsAdd(path, isDraw=false){
                this.paths.push(path);
                if(isDraw){
                    this.drawPath(path);
                }
            },
            //绘制路径
            drawPath(path){
                if(path.type === 'lasso'){
                    this.drawFeatherPolygon(path);
                }else{
                    this.drawPathLine(path);
                }
                this.callFuncUpdate();
            },
            // 羽化并填充多边形
            drawFeatherPolygon(path) {
                let points = path.points;
                let ctx = this.dom_ctx;
                ctx.filter = `blur(${path.featherValue}px)`; // 设置模糊效果
                ctx.beginPath();
                ctx.moveTo(points[0].x, points[0].y);
                for (let i = 1; i < points.length; i++) {
                    const dx = points[i].x - points[i - 1].x;
                    const dy = points[i].y - points[i - 1].y;
                    const length = Math.sqrt(dx * dx + dy * dy);
                    const angle = Math.atan2(dy, dx);
                    const featherX = points[i - 1].x + Math.cos(angle) * path.featherValue; // 羽化半径
                    const featherY = points[i - 1].y + Math.sin(angle) * path.featherValue; // 羽化半径
                    ctx.lineTo(featherX, featherY);
                }
                ctx.closePath();
                ctx.fillStyle = path.fillColor; // 羽化颜色
                ctx.fill();
                ctx.filter = 'none'; // 重置滤镜
            },
            // 绘制路径
            drawPathLine(path, isTempCtx=false) {
                if (!path || !path.points || path.points.length < 1) return;
                let ctx = isTempCtx ? this.dom_ctx_temp : this.dom_ctx;
                ctx.save();

                let points = path.points;
                ctx.beginPath();
                ctx.strokeStyle = path.color || this.currentBrushColor;
                ctx.lineWidth = path.width || this.currentLineWidth;
                ctx.lineCap = 'round';
                ctx.lineJoin = 'round';

                if (points.length === 1) {
                    // 如果路径只有一个点，则画一个圆点
                    ctx.arc(points[0].x, points[0].y, path.width || this.currentLineWidth / 2, 0, 2 * Math.PI);
                    ctx.fillStyle = path.color || this.currentBrushColor;
                    ctx.fill();
                } else {
                    ctx.moveTo(points[0].x, points[0].y);

                    if (path.type === 'brush') {
                        // 毛笔效果
                        for (let i = 1; i < points.length; i++) {
                            // ctx.globalAlpha = 1;
                            ctx.lineWidth = points[i].width;
                            ctx.lineTo(points[i].x, points[i].y);
                            ctx.stroke();
                            ctx.beginPath();
                            ctx.moveTo(points[i].x, points[i].y);
                        }
                    } else {
                        // 普通画笔效果
                        for (let i = 1; i < points.length - 2; i++) {
                            const xc = (points[i].x + points[i + 1].x) / 2;
                            const yc = (points[i].y + points[i + 1].y) / 2;
                            ctx.quadraticCurveTo(points[i].x, points[i].y, xc, yc);
                        }
                    }
                    ctx.stroke();
                }
                ctx.restore();
            },

            // 工具方法：转换颜色格式
            hexToRgb(hex) {
                const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex);
                return result ? {
                    r: parseInt(result[1], 16),
                    g: parseInt(result[2], 16),
                    b: parseInt(result[3], 16)
                } : null;
            },
            //清空画布
            canvasClearEmpty(isTemp=false){
                let ctx = isTemp ? this.dom_ctx_temp : this.dom_ctx;
                ctx.fillStyle = 'transparent';
                ctx.clearRect(0, 0, this.dom_canvas.width, this.dom_canvas.height);
                ctx.save();
            },
            // 绘制图像
            drawImage() {
                let ctx = this.dom_ctx;
                // 清空画布
                this.canvasClearEmpty();

                // 绘制图片
                if (this.currentImage) {
                    ctx.drawImage(this.currentImage, 0, 0, this.dom_canvas.width, this.dom_canvas.height);
                }

                ctx.restore();

                // 绘制所有路径
                this.paths.forEach((path, index) => {
                    this.drawPath(path);
                    if (this.selectedPaths.has(index)) {
                        this.drawPathBoundingBox(path);
                    }
                });

                // 绘制选择框
                this.drawSelectionBox();
                // 更新删除按钮位置
                this.updateDeleteButtons();
                this.callFuncUpdate();
            },
            // 绘制路径边界框
            drawPathBoundingBox(path) {
                const bounds = this.getPathBounds(path);
                if(!bounds) return;
                let ctx = this.dom_ctx;
                ctx.save();
                ctx.strokeStyle = '#0066ff';
                ctx.setLineDash([5, 5]);
                ctx.strokeRect(bounds.minX - 5, bounds.minY - 5,
                                  bounds.maxX - bounds.minX + 10,
                                  bounds.maxY - bounds.minY + 10);
                ctx.restore();
            },
            // 获取路径边界
            getPathBounds(path) {
                if (!path || path.length < 1) return;
                let minX = Infinity, minY = Infinity;
                let maxX = -Infinity, maxY = -Infinity;
                path.points.forEach(point => {
                    minX = Math.min(minX, point.x);
                    minY = Math.min(minY, point.y);
                    maxX = Math.max(maxX, point.x);
                    maxY = Math.max(maxY, point.y);
                });
                return { minX, minY, maxX, maxY };
            },
            // 绘制选择框
            drawSelectionBox() {
                const self = this;
                const Selection = self.Selection;
                if(!Selection.Active){
                    return;
                }
                let ctx = this.dom_ctx;
                const startX = Selection.Start.x;
                const startY = Selection.Start.y;
                const endX = Selection.End.x;
                const endY = Selection.End.y;

                ctx.save();
                ctx.fillStyle = Selection.FillStyle;
                ctx.fillRect(
                    Math.min(startX, endX),
                    Math.min(startY, endY),
                    Math.abs(endX - startX),
                    Math.abs(endY - startY)
                );
                ctx.strokeStyle = Selection.Color;
                ctx.lineWidth = 1; // 设置边框线宽为1px
                ctx.strokeRect(
                    Math.min(startX, endX),
                    Math.min(startY, endY),
                    Math.abs(endX - startX),
                    Math.abs(endY - startY)
                );
                ctx.restore();
            },
            // 创建删除按钮
            createDeleteButton(pathIndex, x, y) {
                const btn = document.createElement('button');
                btn.className = 'ksa-piceditor-delete-btn';
                btn.innerHTML = '×';
                btn.style.left = `${x}px`;
                btn.style.top = `${y}px`;
                btn.addEventListener('mousedown', (e) => { // 使用 addEventListener
                    this.paths.splice(pathIndex, 1);
                    this.selectedPaths.delete(pathIndex);
                    this.drawImage();
                    this.updateDeleteButtons();
                    e.stopPropagation();
                });
                this.dom_canvas_wrapper.appendChild(btn);
                return btn;
            },
            // 更新删除按钮位置
            updateDeleteButtons() {
                this.removeDeleteButtons();
                this.selectedPaths.forEach(pathIndex => {
                    const path = this.paths[pathIndex];
                    const bounds = this.getPathBounds(path);
                    if(!bounds){
                        return;
                    }
                    const x = bounds.maxX;
                    const y = bounds.minY;
                    this.createDeleteButton(pathIndex, x, y);

                });
            },
            // 移除所有删除按钮
            removeDeleteButtons() {
                const buttons = this.dom_canvas_container.querySelectorAll('.ksa-piceditor-delete-btn');
                buttons.forEach(btn => btn.remove());
            },
            // 撤销功能
            undo() {
                if (this.paths.length > 0) {
                    this.paths.pop();
                    this.drawImage();
                }
            },
            polygon_start(x, y) {
                if(this.polygon.isDrawing){
                    return;
                }
                if(this.polygon_points.length){
                    this.canvasClearEmpty(true);
                    this.polygon_points = [];
                    return;
                }

                this.polygon_points.push({ x, y });
                this.polygon_GroupPoint.push(this.polygon_points);
                this.polygon.isDrawing = true;
                this.dom_ctx_temp.beginPath();
                this.dom_ctx_temp.moveTo(x, y);
                this.dom_ctx_temp.strokeStyle = this.lineColor;
                this.dom_ctx_temp.lineWidth = this.lineWidth;
                this.dom_ctx_temp.stroke();
            },
            // 继续绘制多边形
            polygon_continue(x, y) {
                if (this.polygon.isDrawing) {
                    let lastPoint = this.polygon_points[this.polygon_points.length - 1];
                    if(lastPoint.x === x && lastPoint.y === y){
                        return;
                    }
                    this.polygon_points.push({ x, y });
                    this.dom_ctx_temp.lineTo(x, y);
                    this.dom_ctx_temp.strokeStyle = this.polygon.lineColor; // 确保每次绘制线段时都设置线条颜色
                    this.dom_ctx_temp.lineWidth = this.polygon.lineWidth; // 确保每次绘制线段时都设置线条宽度
                    this.dom_ctx_temp.stroke();
                }
            },
            // 完成绘制多边形
            polygon_end() {
                if (this.polygon.isDrawing) {
                    // 连接多边形的起点和终点
                    this.polygon_continue(this.polygon_points[0].x, this.polygon_points[0].y);
                    this.pathsAdd({
                        type : 'lasso', //类型 羽化
                        featherValue : this.featherValue, //羽化值
                        fillColor : this.featherColor, //填充颜色
                        points : this.polygon_points,
                    }, true);
                    this.polygon.isComplete = true;
                    this.polygon.isDrawing = false;

                }
            },
            // 取消绘制多边形
            polygon_cancel() {
                this.polygon_points = [];
                this.polygon.isDrawing = false;
                this.polygon.isComplete = false;
                this.canvasClearEmpty(true);
            },
            Crop_InitBox(){
                const self = this;
                const cropBox = this.Crop.Box;
                let top = parseInt(self.dom_canvas.height / 2);
                let left = parseInt(self.dom_canvas.width / 2);
                cropBox.left = 0 - left;
                cropBox.top = 0 - top;

                cropBox.tl = {x:left, y:top};
                cropBox.tr = {x:left+self.dom_canvas.width, y:top};
                cropBox.br = {x:left+self.dom_canvas.width, y:top+self.dom_canvas.height};
                cropBox.bl = {x:left, y:top+self.dom_canvas.height};

                this.Crop.Canvas.width = self.dom_canvas.width * 2;
                this.Crop.Canvas.height = self.dom_canvas.height * 2;

                this.Crop.Canvas.style.left = cropBox.left + 'px';
                this.Crop.Canvas.style.top = cropBox.top + 'px';
                this.Crop.Canvas.style.display = 'block';
                this.Crop_DrawBox();
            },
            Crop_InitDefault(){
                const cropBox = this.Crop.Box;
                this.Crop.ActionID = 0;
                this.Crop.Action = null;
                cropBox.left = 0;
                cropBox.top = 0;
                this.Crop.Canvas.style = '';
                this.Crop.Canvas.style.display = 'none';

                let ctx = this.Crop.Ctx;
                ctx.fillStyle = 'transparent';
                ctx.clearRect(0, 0, this.Crop.Canvas.width, this.Crop.Canvas.height);
                ctx.save();
            },
            Crop_DrawBox() {
                const cropBox = this.Crop.Box;
                const ctxTemp = this.Crop.Ctx;
                const canvasTemp = this.Crop.Canvas;
                ctxTemp.clearRect(0, 0, canvasTemp.width, canvasTemp.height);

                // 遮罩
                ctxTemp.fillStyle = 'rgba(0, 0, 0, 0.5)';
                ctxTemp.fillRect(0, 0, canvasTemp.width, canvasTemp.height);

                // 定义四边形的顶点
                const points = [
                    cropBox.tl, // 顶点1
                    cropBox.tr, // 顶点2
                    cropBox.br, // 顶点3
                    cropBox.bl  // 顶点4
                ];

                // 清除任意四边形区域
                ctxTemp.save(); // 保存上下文状态
                ctxTemp.beginPath();

                // 定义四边形路径
                ctxTemp.moveTo(points[0].x, points[0].y);
                for (let i = 1; i < points.length; i++) {
                    ctxTemp.lineTo(points[i].x, points[i].y);
                }
                ctxTemp.closePath();

                // 使用裁剪区域将四边形设为可操作范围
                ctxTemp.clip();

                // 用透明色清除该区域
                ctxTemp.clearRect(0, 0, canvasTemp.width, canvasTemp.height);

                ctxTemp.restore(); // 恢复上下文状态

                // 网格
                this.Crop_drawGrid(cropBox.x, cropBox.y, cropBox.width, cropBox.height);

            },
            /**
             * 裁剪 绘制网格
             * @constructor
             */
            Crop_drawGrid() {
                const cropBox = this.Crop.Box;
                const size = 10;
                const sizeB = size / 2;
                //四个角坐标 子级值{x:0,y:0}
                let tl = cropBox.tl; //左上角
                let tr = cropBox.tr; //右上角
                let bl = cropBox.bl; //左下角
                let br = cropBox.br; //右下角

                const ctxTemp = this.Crop.Ctx;
                const isTransform = this.Crop.isTransform; // 是否为透视裁剪
                const cells = 4;


                // 计算行列之间的间距因子
                for (let i = 0; i <= cells; i++) {
                    // 使用线性插值来找到垂直线的起点和终点
                    let startX = tl.x + (tr.x - tl.x) * (i / cells);
                    let startY = tl.y + (tr.y - tl.y) * (i / cells);
                    let endX = bl.x + (br.x - bl.x) * (i / cells);
                    let endY = bl.y + (br.y - bl.y) * (i / cells);


                    ctxTemp.strokeStyle = 'rgba(77, 127, 255, 0.85)';
                    ctxTemp.lineWidth = 1;
                    ctxTemp.beginPath();
                    ctxTemp.moveTo(startX, startY);
                    ctxTemp.lineTo(endX, endY);
                    ctxTemp.stroke();
                    if(i === 0 || i === cells) {
                        ctxTemp.fillStyle = '#ffffff';
                        ctxTemp.fillRect(startX - sizeB, startY - sizeB, size, size);
                        ctxTemp.fillRect(endX - sizeB, endY - sizeB, size, size);
                    }
                }

                for (let i = 0; i <= cells; i++) {
                    // 使用线性插值来找到水平线的起点和终点
                    let startX = tl.x + (bl.x - tl.x) * (i / cells);
                    let startY = tl.y + (bl.y - tl.y) * (i / cells);
                    let endX = tr.x + (br.x - tr.x) * (i / cells);
                    let endY = tr.y + (br.y - tr.y) * (i / cells);

                    ctxTemp.strokeStyle = 'rgba(77, 127, 255, 0.85)';
                    ctxTemp.lineWidth = 1;
                    ctxTemp.beginPath();
                    ctxTemp.moveTo(startX, startY);
                    ctxTemp.lineTo(endX, endY);
                    ctxTemp.stroke();
                    if(i === 0 || i === cells) {
                        ctxTemp.fillStyle = '#ffffff';
                        ctxTemp.fillRect(startX - sizeB, startY - sizeB, size, size);
                        ctxTemp.fillRect(endX - sizeB, endY - sizeB, size, size);
                    }
                }
            },

            Crop_detectCorner(mouseX, mouseY) {
                const size = 5;
                const cropBox = this.Crop.Box;
                //四个角坐标 子级值{x:0,y:0}
                let tl = cropBox.tl; //左上角
                let tr = cropBox.tr; //右上角
                let bl = cropBox.bl; //左下角
                let br = cropBox.br; //右下角

                mouseX -= cropBox.left;
                mouseY -= cropBox.top;
                const corners = [
                    { x: tl.x, y: tl.y, corner: 'tl' },
                    { x: tr.x, y: tr.y, corner: 'tr' },
                    { x: bl.x, y: bl.y, corner: 'bl' },
                    { x: br.x, y: br.y, corner: 'br' },
                ];

                for (const corner of corners) {
                    if (
                        mouseX >= corner.x - size &&
                        mouseX <= corner.x + size &&
                        mouseY >= corner.y - size &&
                        mouseY <= corner.y + size
                    ) {
                        return corner.corner;
                    }
                }

                // 定义一个阈值，用来定义“在边上”的容差
                const threshold = 5; // 可以根据需求调整这个值

                function pointToSegmentDistance(px, py, sx1, sy1, sx2, sy2) {
                    // 计算点到线段的距离
                    let A = px - sx1;
                    let B = py - sy1;
                    let C = sx2 - sx1;
                    let D = sy2 - sy1;

                    let dot = A * C + B * D;
                    let len_sq = C * C + D * D;
                    let param = len_sq !== 0 ? dot / len_sq : -1;

                    let xx, yy;

                    if (param < 0) {
                        xx = sx1;
                        yy = sy1;
                    } else if (param > 1) {
                        xx = sx2;
                        yy = sy2;
                    } else {
                        xx = sx1 + param * C;
                        yy = sy1 + param * D;
                    }

                    let dx = px - xx;
                    let dy = py - yy;
                    return Math.sqrt(dx * dx + dy * dy);
                }

                // 检查每个边
                if (pointToSegmentDistance(mouseX, mouseY, tl.x, tl.y, tr.x, tr.y) <= threshold) return 't';
                if (pointToSegmentDistance(mouseX, mouseY, tr.x, tr.y, br.x, br.y) <= threshold) return 'r';
                if (pointToSegmentDistance(mouseX, mouseY, br.x, br.y, bl.x, bl.y) <= threshold) return 'b';
                if (pointToSegmentDistance(mouseX, mouseY, bl.x, bl.y, tl.x, tl.y) <= threshold) return 'l';

                return null;
            },

            Crop_resizeCropBox(action, mouseX, mouseY) {
                const cropBox = this.Crop.Box;
                const padding = 10; //裁剪框 允许的最小边距
                const minSize = 20; //裁剪框 最小尺寸
                const isTransform = this.Crop.isTransform; //是否为透视裁剪
                mouseX -= cropBox.left;
                mouseY -= cropBox.top;

                mouseX = Math.max(mouseX, padding);
                mouseY = Math.max(mouseY, padding);
                //检查是否存在四个角的坐标动作
                if(cropBox[action]){
                    cropBox[action].x = mouseX;
                    cropBox[action].y = mouseY;
                }
                // debug('裁剪框坐标', JSON.stringify(cropBox));
                //如果是透视裁剪 则不继续
                if(!this.Crop.isTransform) {
                    //非透视裁剪 锁定四边 始终为矩形
                    switch (action) {
                        case 'tl':
                            cropBox.bl.x = mouseX;
                            cropBox.tr.y = mouseY;
                            break;
                        case 'tr':
                            cropBox.tl.y = mouseY;
                            cropBox.br.x = mouseX;
                            break;
                        case 'bl':
                            cropBox.tl.x = mouseX;
                            cropBox.br.y = mouseY;

                            break;
                        case 'br':
                            cropBox.tr.x = mouseX;
                            cropBox.bl.y = mouseY;
                            break;
                        case 't':
                            mouseY = Math.min(mouseY, cropBox.bl.y - padding * 2);
                            cropBox.tl.y = mouseY;
                            cropBox.tr.y = mouseY;
                            break;
                        case 'l':
                            mouseX = Math.min(mouseX, cropBox.tr.x - padding * 2);
                            cropBox.tl.x = mouseX;
                            cropBox.bl.x = mouseX;
                            break;
                        case 'r':
                            mouseX = Math.max(mouseX, cropBox.tl.x + padding * 2);
                            mouseX = Math.min(mouseX, this.Crop.Canvas.width - padding);
                            cropBox.tr.x = mouseX;
                            cropBox.br.x = mouseX;
                            break;
                        case 'b':
                            mouseY = Math.max(mouseY, cropBox.tl.y + padding * 2);
                            mouseY = Math.min(mouseY, this.Crop.Canvas.height - padding);
                            cropBox.bl.y = mouseY;
                            cropBox.br.y = mouseY;
                            break;
                    }
                }
                switch (action) {
                    case 'tl':
                        cropBox.tl.x = Math.max(cropBox.tl.x, padding);
                        cropBox.tl.x = Math.min(cropBox.tl.x, cropBox.tr.x - padding * 2);
                        cropBox.tl.y = Math.max(cropBox.tl.y, padding);
                        break;
                    case 'tr':
                        cropBox.tr.x = Math.min(cropBox.tr.x, this.Crop.Canvas.width - padding);
                        cropBox.tr.x = Math.max(cropBox.tr.x, cropBox.tl.x + padding * 2);
                        cropBox.tr.y = Math.max(cropBox.tr.y, padding);
                        cropBox.tr.y = Math.min(cropBox.tr.y, cropBox.br.y - padding * 2);
                        break;
                    case 'bl':
                        cropBox.bl.x = Math.max(cropBox.bl.x, padding);
                        cropBox.bl.x = Math.min(cropBox.bl.x, cropBox.br.x - padding * 2);
                        cropBox.bl.y = Math.max(cropBox.bl.y, cropBox.tl.y + padding * 2);
                        cropBox.bl.y = Math.min(cropBox.bl.y, this.Crop.Canvas.height - padding);
                        break;
                    case 'br':
                        cropBox.br.x = Math.min(cropBox.br.x, this.Crop.Canvas.width - padding);
                        cropBox.br.x = Math.max(cropBox.br.x, cropBox.bl.x + padding * 2);
                        cropBox.br.y = Math.max(cropBox.br.y, cropBox.tr.y + padding * 2);
                        cropBox.br.y = Math.min(cropBox.br.y, this.Crop.Canvas.height - padding);
                        break;
                    case 't':

                        break;
                    case 'l':

                        break;
                    case 'r':

                        break;
                    case 'b':

                        break;
                }
            },
            Crop_updateCursor(corner) {
                let cursor = 'default';
                if (corner) {
                    switch (corner) {
                        case 'tl':
                            cursor = 'nw-resize';
                            break;
                        case 'br':
                            cursor = 'nw-resize';
                            break;
                        case 'tr':
                            cursor = 'ne-resize';
                            break;
                        case 'bl':
                            cursor = 'ne-resize';
                            break;
                        case 't':
                            cursor = this.Crop.isTransform ? '' : 'n-resize';
                            break;
                        case 'b':
                            cursor = this.Crop.isTransform ? '' : 's-resize';
                            break;
                        case 'l':
                            cursor = this.Crop.isTransform ? '' : 'w-resize';
                            break;
                        case 'r':
                            cursor = this.Crop.isTransform ? '' : 'e-resize';
                            break;
                    }
                }
                this.Crop.Canvas.style.cursor = cursor;
            },
            /**
             * 裁剪应用生效
             * @constructor
             */
            Crop_Apply(){
                const self = this;
                const cropBox = self.Crop.Box;
                // 绘制图片
                if (this.currentImage) {
                    if(this.Crop.isTransform) {
                        let width = this.dom_canvas.width;
                        let height = this.dom_canvas.height;
                        // 定义四个点的坐标 (可以在实际场景中通过鼠标点击获取)
                        const srcPoints = [
                            {x:(cropBox.tl.x + cropBox.left), y:(cropBox.tl.y + cropBox.top)}, // 左上角
                            {x:(cropBox.tr.x + cropBox.left), y:(cropBox.tr.y + cropBox.top)}, // 右上角
                            {x:(cropBox.br.x + cropBox.left), y:(cropBox.br.y + cropBox.top)}, // 右下角
                            {x:(cropBox.bl.x + cropBox.left), y:(cropBox.bl.y + cropBox.top)}   // 左下角
                        ];
                        // 目标矩形的坐标
                        const destPoints = [
                            { x: 0, y: 0 }, // 左上角
                            { x: width, y: 0 }, // 右上角
                            { x: width, y: height }, // 右下角
                            { x: 0, y: height } // 左下角
                        ];
                        // 调用透视变换函数
                        let matrix = self.Crop_computePerspectiveMatrix(srcPoints, destPoints);
                        // 应用透视变换
                        let tempCanvas = self.Crop_applyPerspectiveTransform(this.dom_ctx, width, height, matrix);
                        this.currentImage = tempCanvas;

                        tempCanvas = this.createVirtualCanvas(tempCanvas.width, tempCanvas.height);
                        tempCtx = tempCanvas.getContext('2d');
                        tempCtx.drawImage(this.currentImage, 0, 0, tempCanvas.width, tempCanvas.height);
                        this.originalImage = tempCanvas;

                    }else{
                        const drawX = cropBox.tl.x + cropBox.left;
                        const drawY = cropBox.tl.y + cropBox.top;
                        let crop_width = cropBox.tr.x - cropBox.tl.x;
                        let crop_height = cropBox.br.y - cropBox.tr.y;
                        let tempCanvas = this.createVirtualCanvas(crop_width, crop_height);
                        let tempCtx = tempCanvas.getContext('2d');
                        tempCtx.drawImage(this.currentImage, drawX, drawY, crop_width, crop_height, 0, 0, crop_width, crop_height);
                        this.currentImage = tempCanvas;

                        tempCanvas = this.createVirtualCanvas(crop_width, crop_height);
                        tempCtx = tempCanvas.getContext('2d');
                        tempCtx.drawImage(this.originalImage, drawX, drawY, crop_width, crop_height, 0, 0, crop_width, crop_height);
                        this.originalImage = tempCanvas;
                    }
                }
                this.resizeCanvas();
                this.Crop_InitBox();
            },
            /**
             * 计算透视变换矩阵
             * @returns {Array} - 3x3 透视矩阵
             * @param src 透视点 四个角坐标
             * @param dst 图像四个角坐标
             */
            Crop_computePerspectiveMatrix(src, dst) {
                const matrix = [];
                for (let i = 0; i < 4; i++) {
                    const sx = src[i].x, sy = src[i].y;
                    const dx = dst[i].x, dy = dst[i].y;
                    matrix.push(
                        [sx, sy, 1, 0, 0, 0, -dx * sx, -dx * sy],
                        [0, 0, 0, sx, sy, 1, -dy * sx, -dy * sy]
                    );
                }

                const B = [];
                for (let i = 0; i < 4; i++) {
                    B.push(dst[i].x);
                    B.push(dst[i].y);
                }

                // 使用原生方法求解线性方程组
                const h = new Array(8).fill(0);
                for (let i = 0; i < 8; i++) {
                    for (let j = i; j < 8; j++) {
                        if (Math.abs(matrix[j][i]) > Math.abs(matrix[i][i])) {
                            [matrix[i], matrix[j]] = [matrix[j], matrix[i]];
                            [B[i], B[j]] = [B[j], B[i]];
                        }
                    }
                    for (let j = i + 1; j < 8; j++) {
                        const ratio = matrix[j][i] / matrix[i][i];
                        for (let k = i; k < 8; k++) {
                            matrix[j][k] -= ratio * matrix[i][k];
                        }
                        B[j] -= ratio * B[i];
                    }
                }
                for (let i = 7; i >= 0; i--) {
                    let sum = 0;
                    for (let j = i + 1; j < 8; j++) {
                        sum += matrix[i][j] * h[j];
                    }
                    h[i] = (B[i] - sum) / matrix[i][i];
                }
                h.push(1);
                return h;
            },
            /**
             * 应用透视变换
             * @param ctx
             * @param width
             * @param height
             * @param hMatrix
             */
            Crop_applyPerspectiveTransform(ctx, width, height, hMatrix) {
                debug('应用变换', width, height);
                const srcData = ctx.getImageData(0, 0, width, height);
                let dstCanvas = this.createVirtualCanvas(width, height);
                let dstCtx = dstCanvas.getContext('2d');
                const dstData = dstCtx.createImageData(width, height);

                // 计算逆矩阵
                let inverseMatrix = this.Crop_invertMatrix3x3(hMatrix);
                let minX=width , minY=height, maxX=0, maxY=0;
                for (let y = 0; y < height; y++) {
                    for (let x = 0; x < width; x++) {
                        // 目标点到源点的坐标映射
                        const wx = inverseMatrix[0][0] * x + inverseMatrix[0][1] * y + inverseMatrix[0][2];
                        const wy = inverseMatrix[1][0] * x + inverseMatrix[1][1] * y + inverseMatrix[1][2];
                        const w = inverseMatrix[2][0] * x + inverseMatrix[2][1] * y + inverseMatrix[2][2];

                        const srcX = Math.round(wx / w);
                        const srcY = Math.round(wy / w);

                        if (srcX >= 0 && srcX < width && srcY >= 0 && srcY < height) {
                            if(srcX < minX){
                                minX = srcX;
                            }
                            if(srcY < minY){
                                minY = srcY;
                            }
                            if(srcX > maxX){
                                maxX = srcX;
                            }
                            if(srcY > maxY){
                                maxY = srcY;
                            }
                            const srcIndex = (srcY * width + srcX) * 4;
                            const dstIndex = (y * width + x) * 4;

                            dstData.data[dstIndex] = srcData.data[srcIndex];       // 红色通道
                            dstData.data[dstIndex + 1] = srcData.data[srcIndex + 1]; // 绿色通道
                            dstData.data[dstIndex + 2] = srcData.data[srcIndex + 2]; // 蓝色通道
                            dstData.data[dstIndex + 3] = srcData.data[srcIndex + 3]; // 透明度
                        }
                    }
                }

                dstCtx.putImageData(dstData, 0, 0);

                let tempCanvas_2 = this.createVirtualCanvas(maxX - minX, maxY - minY);
                let tempCtx_2 = tempCanvas_2.getContext('2d');
                tempCtx_2.drawImage(dstCanvas, 0, 0, tempCanvas_2.width, tempCanvas_2.height);
                dstCanvas = null;
                dstCtx = null;

                debug('应用变换', tempCanvas_2.width, tempCanvas_2.height);

                return tempCanvas_2;
            },
            /**
             * 计算 3x3 矩阵的逆矩阵
             * @param matrix
             * @return {number[][]}
             */
            Crop_invertMatrix3x3(matrix) {
                const det = matrix[0] * (matrix[4] * matrix[8] - matrix[5] * matrix[7]) -
                            matrix[1] * (matrix[3] * matrix[8] - matrix[5] * matrix[6]) +
                            matrix[2] * (matrix[3] * matrix[7] - matrix[4] * matrix[6]);

                if (det === 0) throw new Error("矩阵不可逆");

                const invDet = 1 / det;

                return [
                    [
                        (matrix[4] * matrix[8] - matrix[5] * matrix[7]) * invDet,
                        (matrix[2] * matrix[7] - matrix[1] * matrix[8]) * invDet,
                        (matrix[1] * matrix[5] - matrix[2] * matrix[4]) * invDet
                    ],
                    [
                        (matrix[5] * matrix[6] - matrix[3] * matrix[8]) * invDet,
                        (matrix[0] * matrix[8] - matrix[2] * matrix[6]) * invDet,
                        (matrix[2] * matrix[3] - matrix[0] * matrix[5]) * invDet
                    ],
                    [
                        (matrix[3] * matrix[7] - matrix[4] * matrix[6]) * invDet,
                        (matrix[1] * matrix[6] - matrix[0] * matrix[7]) * invDet,
                        (matrix[0] * matrix[4] - matrix[1] * matrix[3]) * invDet
                    ]
                ];
            }
        },


});